package entities.concept;

import java.util.HashSet;

import entities.concept.PConcept;

/**
 * A general description of concepts
 * @author j55wu
 *
 */
public abstract class Concept {

	public static final String PRIME = "*";

	// Concept subclasses should implement functionality to return a "primed" copy of themselves
	public abstract Concept getPrimeCopy();
	
	
	public String getShortURI(){
		String uri = null;
		
		return uri;
	}
	
	//An inefficient recursive implementation
	//note that no simplification is done, e.g., not (not A) = A. This makes a difference in absorption, so mind your coding!
	public static HashSet<Concept> reduceToDisjuncts(Concept c){
		HashSet<Concept> ors = new HashSet<Concept>();
		if(c instanceof OrConcept){
			OrConcept oc = (OrConcept) c;
			for(Concept cc:oc.getConceptSet()){
				ors.addAll(reduceToDisjuncts(cc));
			}
		}else{
			ors.add(c);
		}
		return ors;
	}
	
	public static HashSet<Concept> reduceToConjuncts(Concept c){
		HashSet<Concept> ands = new HashSet<Concept>();
		if(c instanceof AndConcept){
			AndConcept ac = (AndConcept) c;
			for(Concept cc:ac.getConceptSet()){
				ands.addAll(reduceToConjuncts(cc));
			}
		}else{
			ands.add(c);
		}
		return ands;
	}
	
	public boolean isTop(){
		if(this instanceof PConcept){
			PConcept pc = (PConcept) this;
			return pc.isTop();
		}else if(this instanceof OrConcept){
			boolean ret = false;
			OrConcept or = (OrConcept) this; 
			for(Concept o:or.getConceptSet()){
				ret |= o.isTop();
			}
			if(ret){
				return ret;
			}
		}else if(this instanceof NotConcept){
			NotConcept nc = (NotConcept)this;
			return nc.getConcept().isBot();
		}
		return false;
	}
	
	public boolean isBot(){
		if(this instanceof PConcept){
			PConcept pc = (PConcept) this;
			return pc.isBottom();
		}/*else if(this.isBinarySimple()){
			// A and B, to see if B is not A
			AndConcept as = (AndConcept) this;
			Iterator<Concept> i = as.getConceptSet().iterator();
			Concept a = i.next();
			Concept b = i.next();
			if(a instanceof NotConcept){
				NotConcept n = (NotConcept)a;
				
			}
		}*/
		
		if (this instanceof NotConcept) {
			return ((NotConcept)this).getConcept().isTop();
		}
		
		return false;
	}
	
	public boolean isBinarySimple(){
		if(this instanceof AndConcept){
			AndConcept ands = (AndConcept) this;
			if(ands.getConceptSet().size()!=2){
				return false;
			}
			for(Concept con:ands.getConceptSet()){
				if(!(con instanceof PConcept)){
					return false;
				}
			}
			return true;
		}
		return false;
	}
	
	//negated concept names
	public boolean isSimpleNot(){
		if(this instanceof NotConcept){
			NotConcept nc = (NotConcept)this;
			if(nc.getConcept() instanceof PConcept
					&& !nc.getConcept().isTop()
					&& !nc.getConcept().isBot()){
				return true;
			}
		}
		return false;
	}
	
	
    /*@Override public boolean equals(Object other) {
        boolean result = false;
        if (other instanceof PConcept) {
        	PConcept that = (PConcept) other;
            result = (this.getClass().equals(that.getClass())
            		&& that.equals(this));
        }else if(other instanceof AndConcept){
        	AndConcept that = (AndConcept) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof OrConcept){
        	OrConcept that = (OrConcept) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof ExistsConcept){
        	ExistsConcept that = (ExistsConcept) other;
        	result = (this.getClass().equals(that.getClass())
    			&& that.equals(this));
        }else if(other instanceof UniversalConcept){
        	UniversalConcept that =(UniversalConcept) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof DomainConcept){
        	DomainConcept that = (DomainConcept) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof DomainConceptEQ){
        	DomainConceptEQ that = (DomainConceptEQ) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof DomainConceptLT){
        	DomainConceptLT that = (DomainConceptLT) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }else if(other instanceof DomainConceptLTEQ){
        	DomainConceptLTEQ that = (DomainConceptLTEQ) other;
        	result = (this.getClass().equals(that.getClass())
        			&& that.equals(this));
        }
        	
        return result;
    }*/

	
}

